import Facebook from "../Facebook/Facebook";
import MsgSystem from "../MsgSystem/MsgSystem";
import MsgDefine from "../MsgSystem/MsgDefine";
import FacebookPlayerInfoInRank from "../Facebook/FacebookPlayerInfoInRank";
import Utils from "./Util";
import RankManager from "../rank/RankManager";
import Logger from "../Logger/Logger";

/*
 * @Author: HuangLang 
 * @Date: 2018-07-13 15:17:37  
 * @Description :无限循环列表
 * @Last Modified by: HuangLang
 * @Last Modified time: 2018-07-17 14:41:19
 */
/**
 * 滑动方向枚举
 */
export enum ScrollDirEnum {
    Vertical,
    Horizon
}
const { ccclass, property } = cc._decorator;

@ccclass
export default class ScrollHelper extends cc.Component {

    //赋值用的obj
    @property(cc.Node)
    item: cc.Node = null;
    @property(cc.ScrollView)
    Scroll: cc.ScrollView = null;
    //显示用的content
    @property(cc.Node)
    content: cc.Node = null;
    //附加mask组件的对象
    @property(cc.Node)
    maskNode: cc.Node = null;
    //方向，0是垂直方向，1是水平方向
    @property(Number)
    dir: Number = 0;

    @property(cc.Button)
    closeBtn: cc.Button = null;

    @property(cc.Node)
    globalSelect: cc.Node = null;

    @property(cc.Node)
    globalUnSelect: cc.Node = null;

    @property(cc.Node)
    friendSelect: cc.Node = null;

    @property(cc.Node)
    friendUnSelect: cc.Node = null;

    @property(cc.Node)
    emptyNode: cc.Node = null;

    @property(cc.Button)
    shareButton: cc.Button = null;

    //滑动的方向
    public scrollDir: ScrollDirEnum = ScrollDirEnum.Vertical;
    public get ScrollDir() { return this.scrollDir; }
    public set ScrollDir(val) { this.scrollDir = val; }
    private num: number;//需要显示的item数量
    public get Num() { return this.num; }
    public set Num(val) { this.num = val; }
    private itemNum: number;//实际生成item数量
    public get ItemNum() { return this.itemNum; }
    public set ItemNum(val) { this.itemNum = val; }
    public distance = 100;//item之间的间距
    public needSize = 0;//需求要求的高度/宽度
    public visibleHeight = 0;//显示范围高度
    public itemsHeight = 0;//物品高度
    public OnScrollFun = null;//滑动回调
    //可见范围
    private minY: number = 0;
    private maxY: number = 0;
    //可以显示的范围，可见范围 超过 可以显示的范围，就刷新列表（把缓存的item放到下面或上面）
    private minVisibleY: number = 0;
    private maxVisibleY: number = 0;
    public initX = this.distance / 2;
    public initY = -this.distance / 2;

    private _rank: Array<FacebookPlayerInfoInRank> = [];

    private isFriendData = false;

    private needLoadGlobalData = true;
    private needLoadFriendData = true;

    onLoad() {
        this.closeBtn.node.on(cc.Node.EventType.TOUCH_START, this.closeHandler, this);
        this.globalSelect.on(cc.Node.EventType.TOUCH_START, this.loadGlobalData, this);
        this.globalUnSelect.on(cc.Node.EventType.TOUCH_START, this.loadGlobalData, this);
        this.friendSelect.on(cc.Node.EventType.TOUCH_START, this.loadFriendData, this);
        this.friendUnSelect.on(cc.Node.EventType.TOUCH_START, this.loadFriendData, this);
        this.shareButton.node.on("click", this.share, this)
    }

    start() {
        Facebook.FBRank.GetGlobalRank();
        MsgSystem.GetInstance().AddListener(MsgDefine.rankLoadFinish, (rank: Array<FacebookPlayerInfoInRank>) => {
            this.refreshListView(rank);
            // this.closeBtn.node.on(cc.Node.EventType.TOUCH_START, this.closeHandler, this);
        }, this);

    }

    private refreshListView(rank: Array<FacebookPlayerInfoInRank>) {
        if(rank == null || rank.length == 0) {
            this.emptyNode.active = true;
            this.content.active = false;
            return;
        }
        this.emptyNode.active = false;
        this.content.active = true;
        this._rank = rank;
        this.num = rank.length;
        this.itemNum = rank.length;
        this.scrollDir = this.dir as ScrollDirEnum;
        this.Init(this.itemNum);
    }

    onDisable() {
        this.closeBtn.node.off(cc.Node.EventType.TOUCH_START, this.closeHandler, this);
        this.globalSelect.off(cc.Node.EventType.TOUCH_START, this.loadGlobalData, this);
        this.globalUnSelect.off(cc.Node.EventType.TOUCH_START, this.loadGlobalData, this);
        this.friendSelect.off(cc.Node.EventType.TOUCH_START, this.loadFriendData, this);
        this.friendUnSelect.off(cc.Node.EventType.TOUCH_START, this.loadFriendData, this);
    }

    Init(num: number) {
        var eventHandler = new cc.Component.EventHandler();
        eventHandler.target = this.node;
        eventHandler.component = "ScrollHelper";
        eventHandler.handler = "OnScroll";
        this.Scroll.scrollEvents.push(eventHandler);
        this.needSize = this.num * this.distance;
        if (this.scrollDir == ScrollDirEnum.Horizon) {
            this.initX = this.distance / 2;
            this.initY = 0;
            this.content.setContentSize(new cc.Size(this.needSize, this.content.getContentSize().height));

        } else {
            this.initX = 0;
            this.initY = -this.distance / 2;
            this.content.setContentSize(new cc.Size(this.content.getContentSize().width, this.needSize));
        }
        this.visibleHeight = this.maskNode.getContentSize().height;
        this.clearList();
        this.InitObjs();
    }

    //初始化可见的item
    private itemsList = new Array();
    InitObjs() {
        let curX = 0;
        let curY = 0;
        for (let i = 0; i < this.itemNum; i++) {
            let obj: cc.Node = cc.instantiate(this.item);
            obj.parent = this.content;
            obj.active = true;
            if (this.scrollDir == ScrollDirEnum.Horizon) {
                curX = this.initX + this.distance * i;
                // console.error("curX:" + curX);
            }
            else {
                curY = this.initY - this.distance * i;
                // console.error("curY:" + curY);
            }
            obj.setPosition(curX, curY);
            this.onRefresh(obj, i.toString(), i);
            this.itemsList.push(obj);
        }
    }

    private clearList(){
        this.itemsList.forEach(element => {
            element.parent && element.parent.removeChild(element);
        });
        this.itemsList = [];
    }

    //计算边界，超过边界则刷新列表
    //offest是左上角原点滑动的偏移量
    private countBorder(offest) {
        let height = this.visibleHeight;//可见高度
        this.minY = offest;//获得相对于左上角原点的最小y值
        this.maxY = offest + height;//获得相对于左上角原点的最大y值
    }

    private miniIdx = 0;
    private maxIdx = 0;
    private curOffset = 0;
    OnScroll() {
        //获取滚动视图相对于左上角原点的当前滚动偏移
        let scrollOffset: cc.Vec2 = this.Scroll.getScrollOffset();
        let offest = 0;
        if (this.scrollDir == ScrollDirEnum.Horizon)
            //水平的offset是负数，为什么会有这么sb的设计，将它取反和垂直方向的统一一下
            offest = -scrollOffset.x;
        else
            offest = scrollOffset.y;
        this.curOffset = offest;
        // this.refresh();
    }

    //强行刷新
    public refresh() {
        let offest = this.curOffset;

        //最大高度，超过该高度，不刷新
        let maxY = this.needSize;
        if (offest < 0 || offest + this.visibleHeight >= maxY)
            return;

        let idx: number = 0;//从0开始
        this.countBorder(offest);
        this.miniIdx = Math.floor(offest / this.distance);
        // console.error("this.miniIdx:" + this.miniIdx);

        this.minVisibleY = this.miniIdx * this.distance;
        this.maxVisibleY = this.maxIdx * this.distance;
        //miniIdx到maxIdx都会刷新
        for (let i = 0; i < this.itemNum; i++) {
            let obj = this.itemsList[i];
            idx = this.miniIdx + i;
            this.refreshItem(idx, i, obj);
        }
        this.maxIdx = this.miniIdx + this.itemNum;
    }

    //idx是UI该刷新的第几个元素
    private refreshItem(idx, objIdx, obj) {
        if (idx < 0 || idx >= this.num)
            return;

        if (!obj) {
            console.error("obj为空！");
            return;
        }
        let curX = 0;
        let curY = 0;
        if (this.scrollDir == ScrollDirEnum.Horizon)
            curX = this.initX + this.distance * idx;
        else
            curY = this.initY - this.distance * idx;
        // console.error("idx:" + idx + ",curX:" + curX + ",curY:" + curY);
        // obj.setPositionX(curX);
        obj.setPosition(cc.v2(curX, curY));
        // obj.setPositionY(curY);
        this.onRefresh(obj, idx, objIdx);
    }

    /**
     * 刷新回调
     * @param obj 
     * @param idx 需求显示的索引
     * @param objIdx 实际的item索引
     */
    private onRefresh(obj, idx: string, objIdx) {

        let textNode = cc.find("sort/text", obj);
        let text = textNode.getComponent(cc.Label);

        let imageNode = cc.find("sort/image", obj);
        var image = imageNode.getComponent(cc.Sprite);

        let rank = Number(idx) + 1;
        if (rank == 1) {
            imageNode.active = true;
            textNode.active = false;
            cc.loader.loadRes("startscene/2048_hz_1.png", cc.SpriteFrame, (err, spriteFrame) => {
                image.spriteFrame = spriteFrame;
            });

        } else if (rank == 2) {
            imageNode.active = true;
            textNode.active = false;
            cc.loader.loadRes("startscene/2048_hz_2.png", cc.SpriteFrame, (err, spriteFrame) => {
                image.spriteFrame = spriteFrame;
            });
        } else if (rank == 3) {
            imageNode.active = true;
            textNode.active = false;
            cc.loader.loadRes("startscene/2048_hz_3.png", cc.SpriteFrame, (err, spriteFrame) => {
                image.spriteFrame = spriteFrame;
            });
        } else {
            imageNode.active = false;
            textNode.active = true;
            text.string = (Number(idx) + 1).toString();
        }

        Utils.LoadHeadImg(cc.find("bg/head", obj), this._rank[objIdx].playerPicUrl);

        let nick = cc.find("name/label", obj).getComponent(cc.Label);
        nick.string = Utils.cutNick(this._rank[objIdx].playerName, 10);

        let score = cc.find("score/value", obj).getComponent(cc.Label);
        score.string = this._rank[objIdx].playerScore.toString();

        if (this.OnScrollFun)
            this.OnScrollFun(obj, idx, objIdx);
    }


    private closeHandler(): void {
        if (this.node.parent) {
            this.node.parent.removeChild(this.node);
        }
    }

    private loadGlobalData(): void {
        if (!this.isFriendData) {
            Logger.log("now is global data")
            return;
        }
        this.isFriendData = false;
        Logger.log("load global data");
        this.globalSelect.active = true;
        this.globalUnSelect.active = false;
        this.friendSelect.active = false;
        this.friendUnSelect.active = true;

        if(this.needLoadGlobalData) {
            this.needLoadGlobalData = false;
            Facebook.FBRank.GetGlobalRank();
        } else {
            let rank = RankManager.getInstance().getGlobalRankList();
            this.refreshListView(rank);
        }
    }

    private loadFriendData(): void {
        if (this.isFriendData) {
            Logger.log("now is friend data")
            return;
        }
        this.isFriendData = true;
        Logger.log("load friend data");
        this.globalSelect.active = false;
        this.globalUnSelect.active = true;
        this.friendSelect.active = true;
        this.friendUnSelect.active = false;

        if(this.needLoadFriendData) {
            this.needLoadFriendData = false;
            Facebook.FBRank.GetFriendRank();
        } else {
            let rank = RankManager.getInstance().getFriendRankList();
            this.refreshListView(rank);
        }

    }

    private share() {
        Facebook.ChooseAsync();
    }
}
